package cn.com.headfree.log.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.gta.edu.sdk.common.dto.ChartDto;
import com.gta.edu.sdk.common.dto.Page;
import com.gta.edu.sdk.common.dto.ResultData;
import com.gta.edu.sdk.common.dto.Sort;
import com.gta.edu.sdk.log.annotation.OperationLog;
import com.gta.edu.sdk.log.contant.LogType;
import com.gta.edu.sdk.log.contant.OperationType;
import com.gta.edu.sdk.log.entity.TLogWarn;
import com.gta.edu.sdk.log.entity.TSysLogInfo;
import com.gta.edu.sdk.util.CommUtil;
import com.gta.edu.sdk.util.RedisClusterUtil;

import cn.com.headfree.call.IDictionaryServerCall;
import cn.com.headfree.log.dto.ChartLogDto;
import cn.com.headfree.log.service.ILogService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

@RestController
@RequestMapping(value = "/log", produces = "application/json;charset=UTF-8")
public class LogController {
	private static final Logger log = Logger.getLogger(LogController.class);
	private final String LOG_REDIS_KEY = "OPERATE_LOG_KEY";
	private final String SYS_CODE_VALUE = "sys_code";
	private final String EXE_RESULT_VALUE = "function_execute_result";
	
	@Value("${log.max_record_num}")
	private int logMaxRecordNum; // 从配置文件中读取写入文件的路径信息
	
	@Value("${sys-code}")
	private String sysCode; // 从配置文件中读取写入文件的路径信息
	
	@Autowired
    private IDictionaryServerCall dictionaryServerCall;
	
	@Autowired
	private ILogService logService;
	
	@RequestMapping(value = "/writeLog", method = RequestMethod.GET)
	public ResultData writeLog() {
		ResultData result = new ResultData();
		try {
			long size = RedisClusterUtil.getInstance().listSize(LOG_REDIS_KEY);
			List<Serializable> list = RedisClusterUtil.getInstance().list(LOG_REDIS_KEY, size);
			if (list != null && list.size() > 0) {
				this.logService.saveLogRecord(list);
			}
			RedisClusterUtil.getInstance().deleteList(LOG_REDIS_KEY, size);
		} catch (Exception e) {
			log.error("写日志数据失败！", e);
		}
		return result;
	}
	
	@OperationLog(detail="分页查询操作日志",operationType=OperationType.SELECT,logType=LogType.SYSTEM)
	@RequestMapping("/findPageLog")
    public JSONObject findPageLog(HttpServletRequest request,TSysLogInfo logInfo,Date startTime,Date endTime,Sort sort, Page<TSysLogInfo> page) {
        JSONObject pageJSONData = null;
        try {
            this.logService.findPageLog(logInfo, startTime, endTime, sort, page);
            if (page.getResult() != null && page.getResult().size() > 0) {
            	ResultData result = this.dictionaryServerCall.findDictionaryByParentValue(request, sysCode, SYS_CODE_VALUE);
            	JSONArray sysCodeJSONArray = null;
            	JSONArray exeResultJSONArray = null;
            	Map<String,String> sysCodeMap = null;
            	Map<String,String> exeResultMap = null;
            	if (result != null && result.isSuccess()) {
            		sysCodeJSONArray = JSONArray.fromObject(result.getData());
            		sysCodeMap = this.madeData(sysCodeJSONArray);
            	}
            	result = this.dictionaryServerCall.findDictionaryByParentValue(request, sysCode, EXE_RESULT_VALUE);
            	if (result != null && result.isSuccess()) {
            		exeResultJSONArray = JSONArray.fromObject(result.getData());
            		exeResultMap = this.madeData(exeResultJSONArray);
            	}
            	TSysLogInfo info = null;
            	for (int i=0;i<page.getResult().size();i++) {
            		info = page.getResult().get(i);
            		if (sysCodeMap != null && sysCodeMap.size() > 0) {
            			info.setSysCode(sysCodeMap.get(info.getSysCode()));
            		}
            		if (exeResultMap != null && exeResultMap.size() > 0) {
            			info.setResultValue(exeResultMap.get(String.valueOf(info.getResult())));
            		}
            	}
            }
            pageJSONData = CommUtil.getPageJSONData(page, true);
        } catch (Exception e) {
            log.error("分页查询操作日志出现了异常！", e);
        }
        return pageJSONData;
    }
	
	private Map<String,String> madeData(JSONArray array){
		Map<String,String> data = new HashMap<String,String>(array.size());
		JSONObject obj = null;
		for (int i = 0;i < array.size();i++) {
			obj = array.getJSONObject(i);
			if (obj != null) {
				data.put(obj.getString("value"), obj.getString("name"));
			}
		}
		return data;
	}
	
	/**
	 * @description 统计日志操作记录
	 * @author fengya
	 * @date 2020年9月29日 上午11:02:59
	 * @param logInfo
	 * @param startTime
	 * @param endTime
	 * @return
	 * ResultData
	 */
	@OperationLog(detail="汇总统计日志操作记录",operationType=OperationType.SELECT,logType=LogType.SYSTEM)
	@RequestMapping("/logOpSummary")
    public ResultData logOpSummary(String sysCode,Date startTime,Date endTime) {
		ResultData result = new ResultData();
		try {
			List<ChartDto> list = this.logService.logOpSummary(sysCode, startTime, endTime);
			result.setData(list);
		} catch (Exception e) {
			log.error("汇总统计日志操作记录失败！", e);
		}
		return result;
	}
	
	@OperationLog(detail="操作日志异常告警汇总",operationType=OperationType.SELECT,logType=LogType.SYSTEM)
	@RequestMapping("/logOpExceptionSummary")
    public ResultData logOpExceptionSummary(HttpServletRequest request,String sysCode,Date startTime,Date endTime) {
		ResultData result = new ResultData();
		try {
			List<ChartLogDto> list = this.logService.logOpExceptionSummary(sysCode, startTime, endTime);
			JSONArray exeResultJSONArray = null;
        	Map<String,String> exeResultMap = null;
			result = this.dictionaryServerCall.findDictionaryByParentValue(request, this.sysCode, EXE_RESULT_VALUE);
        	if (result != null && result.isSuccess()) {
        		exeResultJSONArray = JSONArray.fromObject(result.getData());
        		exeResultMap = this.madeData(exeResultJSONArray);
        	}
        	ChartLogDto dto = null;
        	List<ChartDto> clist = new ArrayList<ChartDto>(list.size());
        	ChartDto cdto = null;
			for (int i=0;i<list.size();i++) {
				dto = list.get(i);
				if (exeResultMap != null && exeResultMap.size() > 0) {
					cdto = new ChartDto();
					cdto.setLabel(exeResultMap.get(String.valueOf(dto.getLabel())));
					cdto.setValue(dto.getValue());
					clist.add(cdto);
        		}
			}
			result.setData(clist);
		} catch (Exception e) {
			result.setSuccess(false);
			result.setErrorMsg("操作日志异常告警汇总失败！");
			log.error("操作日志异常告警汇总失败！", e);
		}
		return result;
	}
	
	@OperationLog(detail="写入操作日志告警提醒记录",operationType=OperationType.INSERT,logType=LogType.SYSTEM)
	@RequestMapping("/logWarn")
    public ResultData logWarn() {
		ResultData result = new ResultData();
		try {
			int logRecordNum = this.logService.getLogRecordNum();
			if (logRecordNum > logMaxRecordNum) {
				TLogWarn logWarn = new TLogWarn();
				logWarn.setContext("审计日志即将达到存储上线，请及时备份和清理审计日志，保障系统正常运行！");
				logWarn.setWarnType(1);
				logWarn.setCreateTime(new Date());
				this.logService.save(logWarn);
			}
		} catch (Exception e) {
			log.error("操作日志告警提醒记录失败！", e);
		}
		return result;
	}
	
	@OperationLog(detail="分页查询告警日志记录",operationType=OperationType.SELECT,logType=LogType.SYSTEM)
	@RequestMapping("/findPageLogWarn")
    public JSONObject findPageLogWarn(Sort sort, Page<TLogWarn> page) {
        JSONObject pageJSONData = null;
        try {
            this.logService.findPageLogWarn(sort, page);
            TLogWarn logWarn = null;
            for (int i=0;i<page.getResult().size();i++) {
            	logWarn = page.getResult().get(i);
            	if (logWarn.getWarnType().equals(1)) {
            		logWarn.setWarnTypeName("紧急");
            	}
            }
            pageJSONData = CommUtil.getPageJSONData(page, true);
        } catch (Exception e) {
            log.error("分页查询告警日志记录出现了异常！", e);
        }
        return pageJSONData;
    }
	
	@OperationLog(detail="操作日志备份",operationType=OperationType.OTHER,logType=LogType.SYSTEM)
	@RequestMapping("/logBack")
    public ResultData logBack(int flag) {
		ResultData result = new ResultData();
		try {
			Date dNow = new Date();
			Calendar c = Calendar.getInstance();
			c.setTime(dNow);
			c.add(Calendar.MONTH, -1);
			Date dBefore = c.getTime();
			this.logService.logBack(dBefore,flag);
		} catch (Exception e) {
			result.setSuccess(false);
			result.setErrorMsg("操作日志备份失败！");
			log.error("操作日志备份失败！", e);
		}
		return result;
	}
	
	@OperationLog(detail="清除告警日志",operationType=OperationType.DELETE,logType=LogType.SYSTEM)
	@RequestMapping("/clearRecord")
    public ResultData clearRecord() {
		ResultData result = new ResultData();
		try {
			this.logService.clearRecord();
		} catch (Exception e) {
			result.setSuccess(false);
			result.setErrorMsg("清除告警日志失败！");
			log.error("清除告警日志失败！", e);
		}
		return result;
	}
}
